#include "LsCommand.hpp"
#include "Util.hpp"
#include "Path.hpp"
#include "Trace.hpp"

LsCommand::LsCommand()
{
	showHiddenFiles = false;
	detailView = false;
	sortOrder = sortByName;
}

LsCommand::LsCommand(string cmd)
{
	vector<string> args;
	separateArgs(args, cmd.c_str());
	for(size_t ii=0; ii<args.size(); ii++)
		args[ii] = unquoteString(args[ii].c_str());
	
	initFromTokens(args, ".");
}

LsCommand::LsCommand(vector<string> tokens, string pwd)
{
	initFromTokens(tokens, pwd);
}

void LsCommand::initFromTokens(vector<string> &tokens, string pwd)
{
	showHiddenFiles = false;
	detailView = false;
	sortOrder = sortByName;
	
	for(size_t ii=1; ii<tokens.size(); ii++)
	{
		if(tokens[ii].size()>0 && tokens[ii][0]=='-')
		{
			if(tokens[ii] == "-a" || tokens[ii] == "--all")
				showHiddenFiles = true;
			else if(tokens[ii] == "-l")
				detailView = true;
			else if(tokens[ii] == "-r" || tokens[ii]=="--reverse")
				sortOrder = (LsCommand::SortOrder)(sortOrder|sortReverse);
			else if(tokens[ii] == "-S")
				sortOrder = (LsCommand::SortOrder)(sortBySize | (sortOrder&sortReverse));
			else
				throw MessageException(string("Invalid argument: ")+tokens[ii]);
		}
		else
		{
			Path pwdPath(pwd.c_str());
			Path tokenPath(tokens[ii].c_str());
			paths.push_back(tokenPath.resolve(pwdPath).toString());
		}
	}
	
	if(!paths.size())
		paths.push_back(pwd);
}

string LsCommand::toCommand() const
{
	string ret = "ls";
	
	if(showHiddenFiles)
		ret += " -a";
	if(detailView)
		ret += " -l";
	if((sortOrder&~sortReverse) == sortBySize)
		ret += " -S";
	if(sortOrder & sortReverse)
		ret += " -r";
	
	for(unsigned ii=0; ii<paths.size(); ii++)
	{
		// TODO: Get escaping right here (can't just quote it because wildcards
		// should not be quoted)
		ret += " "+quoteProtectString(paths[ii]);
	}
	
	return ret;
}

void LsCommand::getFieldsNeeded(list<string> &fields) const
{
	fields.push_back("name");
	fields.push_back("type");
	
	if(detailView)
	{
		fields.push_back("size");
		fields.push_back("perm");
		fields.push_back("owner");
		fields.push_back("group");
		fields.push_back("mtime");
		fields.push_back("links");
	}
}

string LsCommand::getPath() const
	{ return paths[0]; }

vector<string> LsCommand::getPaths() const
	{ return paths; }
void LsCommand::setPaths(vector<string> paths)
	{ this->paths = paths; }

bool LsCommand::getShowHidden() const
	{ return showHiddenFiles; }
void LsCommand::setShowHidden(bool showHidden)
	{ this->showHiddenFiles = showHidden; }

bool LsCommand::getIsDetailed() const
	{ return detailView; }
void LsCommand::setIsDetailed(bool detailed)
	{ this->detailView = detailed; }

LsCommand::SortOrder LsCommand::getSortOrder() const
	{ return sortOrder; }
void LsCommand::setSortOrder(LsCommand::SortOrder order)
	{ this->sortOrder = order; }

